#ifndef __TOOL_SCHEDULE_SIM_H__
#define __TOOL_SCHEDULE_SIM_H__

typedef enum _EQ_MODULE_ACTION_ID
{
	EQM_ACT_NONE = 0,

	ACT_EFEM_FOUP_TO_EFEM_R_A,
	ACT_EFEM_FOUP_TO_EFEM_R_B,
	ACT_EFEM_FOUP_TO_EFEM_R_AB,
	ACT_EFEM_R_A_TO_EFEM_ALIGNER,
	ACT_EFEM_R_B_TO_EFEM_ALIGNER,
	ACT_EFEM_R_A_TO_EFEM_COOL,
	ACT_EFEM_R_B_TO_EFEM_COOL,
	ACT_EFEM_R_A_TO_LOADLOCK,
	ACT_EFEM_R_B_TO_LOADLOCK,
	ACT_EFEM_ROBOT_TO_FOUP,
	ACT_EFEM_ALIGNER_TO_EFEM_R_A,
	ACT_EFEM_ALIGNER_TO_EFEM_R_B,
	ACT_ALIGNER_PROCESS,
	ACT_COOL_PROCESS,
	ACT_PM_PROCESS,
	ACT_PM_CLEAN_PROCESS,
	ACT_LOADLOCK_PUMPDOWN,
	ACT_LOADLOCK_BACKFILL,
	ACT_LOADLOCK_TO_TM_ROBOT,
	ACT_LOADLOCK_TO_EFEM_ROBOT,

// 	// general action, shared by several modules
// 	EQM_ACT_PROCESS,
// 	EQM_ACT_PREPARE_MOVE_WAFER_IN,
// 	EQM_ACT_PREPARE_MOVE_WAFER_OUT,
// 	// action of process module
// 	EQM_ACT_PM_CLEAN,
// 	EQM_ACT_PM_OPEN_SV,
// 	EQM_ACT_PM_CLOSE_SV,
// 	// action of transfer module
// 	EQM_ACT_TM_GET_WAFER_FROM_PM,
// 	EQM_ACT_TM_GET_WAFER_FROM_LL,
// 	EQM_ACT_TM_PUT_WAFER_TO_PM,
// 	EQM_ACT_TM_PUT_WAFER_TO_LL,
// 	EQM_ACT_TM_PUMPDOWN,
// 	EQM_ACT_TM_BACKFILL,
// 	EQM_ACT_TM_OPEN_SV,
// 	EQM_ACT_TM_CLOSE_SV,
// 	// action of load lock module
// 	EQM_ACT_LL_OPEN_SV,
// 	EQM_ACT_LL_CLOSE_SV,
// 	// action of EFEM module
// 	EQM_ACT_EFEM_ROBOT_GET_WAFER_FROM_FOUP,
// 	EQM_ACT_EFEM_ROBOT_GET_TWO_WAFER_FROM_FOUP,
// 	EQM_ACT_EFEM_ROBOT_GET_WAFER_FROM_COOL,
// 	EQM_ACT_EFEM_ROBOT_GET_WAFER_FROM_ALIGNER,
// 	EQM_ACT_EFEM_ROBOT_PUT_WAFER_TO_FOUP,
// 	EQM_ACT_EFEM_ROBOT_PUT_WAFER_TO_COOL,
// 	EQM_ACT_EFEM_ROBOT_PUT_WAFER_TO_ALIGNER,
} ACTION_ID;

typedef enum _MODULE_ID
{
	MID_NONE = 0,
	MID_EFEM_ALIGNER,
	MID_EFEM_COOL,
	MID_EFEM_ROBOT,
	MID_TM_LL,
	MID_TM_ROBOT_ARM_ANY,
	MID_TM_ROBOT_ARM_UPPER,
	MID_TM_ROBOT_ARM_LOWER,
	MID_PM_ANY,
	MID_PM_1,
	MID_PM_2,
	MID_PM_3,
	MID_PM_4,
	MID_FOUP_ORGIGINAL,
} MODULE_ID;

typedef enum _FOUP_ID
{
	FID_NONE = 0,
	FID_FOUP_ANY,
	FID_FOUP_1,
	FID_FOUP_2,
	FID_FOUP_3,
	FID_FOUP_4,
	FID_ORIGINAL,
} FOUP_ID;

typedef enum _SLOT_ID
{
	SID_NONE = 0,
	SID_1,
	SID_2,
	SID_3,
	SID_4,
	SID_5,
	SID_6,
	SID_7,
	SID_8,
	SID_9,
	SID_10,
	SID_11,
	SID_12,
	SID_13,
	SID_14,
	SID_15,
	SID_16,
	SID_17,
	SID_18,
	SID_19,
	SID_20,
	SID_21,
	SID_22,
	SID_23,
	SID_24,
	SID_25,
	// for loadlock
	SID_UPPER,
	SID_LOWER,
	SID_UPPER_A,
	SID_UPPER_B,
	SID_LOWER_A,
	SID_LOWER_B,
	// common
	SID_ANY = 100,
	// special slot id
	SID_A,
	SID_B,
	SID_ORIGINAL,
} SLOT_ID;

typedef struct _ACTION
{
	ACTION_ID  action_id;
	int        action_start_time;	// in millisecond
	MODULE_ID  source_module;
	SLOT_ID    source_slot;
	MODULE_ID  target_module;
	SLOT_ID    target_slot;
	unsigned short wafer_id;  // 1-based
} ACTION;

#define INPUT_WAFER_MODE_SERIAL		0
#define INPUT_WAFER_MODE_PARALLEL	1
typedef struct _SCHEDULER
{
	int time_offset;        // in millisecond
	int input_wafer_mode;   // serial or parallel
} SCHEDULER;

typedef struct _MODULE
{
	int   assoc_action_index;	// -1 means idle. element index of 'running_action array'.
//	int   task_start_time;		// in millisecond
} MODULE;
#define IS_MODULE_IDLE(module) ((module).assoc_action_index == -1)
#define IS_MODULE_BUSY(module) ((module).assoc_action_index != -1)

#define IS_PM_IDLE(ptr_state_snapshot, pm_index) IS_MODULE_IDLE(ptr_state_snapshot->current_state.pm[pm_index])

#define IS_LOADLOCK_IDLE(ptr_state_snapshot) IS_MODULE_IDLE(ptr_state_snapshot->current_state.loadlock)
#define IS_LOADLOCK_VACUUM(ptr_state_snapshot) (ptr_state_snapshot->current_state.loadlock_is_vacuum)

typedef struct _SLOT
{
	unsigned short current_wafer_id;    // wafer id in the slot, 0 means empty
} SLOT;
#define IS_SLOT_EMPTY(slot) (slot.current_wafer_id == 0)

typedef struct _SEQUENCE_RECIPE_STEP
{
	MODULE_ID  target_module;
	SLOT_ID    target_slot;
	unsigned int    process_time; // 0 means needn't be processed
} SEQUENCE_RECIPE_STEP;

#define MAX_SEQ_RECIPE_STEP_COUNT   32
typedef struct _SEQUENCE_RECIPE
{
	int step_count;  // actual step count
	SEQUENCE_RECIPE_STEP* steps;
	int clean_time;  // clean time of associated PM, 0 means needn't clean
} SEQUENCE_RECIPE;

typedef struct _WAFER_INFO
{
	unsigned char     current_step;     // 0 -- in FOUP; 1 -- leave FOUP...
	SEQUENCE_RECIPE*  seq_rcp;
} WAFER_INFO;
#define IS_WAFER_DONE(wafer) (wafer.current_step >= seq_rcp.step_count)

#define  PM_CHAMBER_COUNT			1
#define  EFEM_COOL_COUNT			6
#define  MAX_RUNNING_ACTION			16
#define  LOADED_WAFER_COUNT			6
#define  SEARCH_STOP_WAFER_COUNT	2
typedef struct _PF300_P4_STATE
{
	MODULE  pm[PM_CHAMBER_COUNT];
	MODULE  tm_chamber;
	MODULE  tm_robot;
	MODULE  loadlock;
	MODULE  efem_aligner;
	MODULE  efem_cool;
	MODULE  efem_robot;

	MODULE_ID efem_aligner_current_position;
	
	ACTION_ID	loadlock_last_action;
	bool		loadlock_is_vacuum;
	
	SLOT	slot_pm_a[PM_CHAMBER_COUNT];
	SLOT	slot_pm_b[PM_CHAMBER_COUNT];
	
	SLOT	slot_tm_r_upper_a;
	SLOT	slot_tm_r_upper_b;
	SLOT	slot_tm_r_lower_a;
	SLOT	slot_tm_r_lower_b;

	SLOT	slot_ll_upper_a;
	SLOT	slot_ll_upper_b;
	SLOT	slot_ll_lower_a;
	SLOT	slot_ll_lower_b;
	
	SLOT	slot_efem_r_a;
	SLOT	slot_efem_r_b;

	SLOT	slot_efem_aligner;
	SLOT	slot_efem_cool[EFEM_COOL_COUNT];
	int     slot_efem_cool_start_time[EFEM_COOL_COUNT];

	SLOT	slot_efem_foup_a[25];
	SLOT	slot_efem_foup_b[25];
	SLOT	slot_efem_foup_c[25];

	WAFER_INFO loaded_wafer_queue[LOADED_WAFER_COUNT];   // wafer queue

	ACTION running_action[MAX_RUNNING_ACTION];

} PF300_P4_STATE;

#define MAX_POSSIBLE_ACTION_COUNT   32
#define CURRENT_NODE_IN_SEARCH_NOT_EXPANDED   0xff00
#define CURRENT_NODE_IN_SEARCH_TIME           0xff01
#define CURRENT_NODE_IN_SEARCH_DONE           0xff02

class PF300_P4_STATE_SNAPSHOT
{
public:

public:
	PF300_P4_STATE  current_state;
	int             current_node_in_search;
	ACTION          possible_actions[MAX_POSSIBLE_ACTION_COUNT];
	int             possible_action_count;
	int             time_offset;
};


#endif
